home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Networking / MoreNetworkSetup / MoreTextUtils / MoreTextUtils.cp next >
Encoding:
Text File  |  2000-09-28  |  8.7 KB  |  405 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        MoreTextUtils.cp
  3.  
  4.     Contains:    
  5.  
  6.     Written by:    Pete Gontier
  7.  
  8.     Copyright:    Copyright (c) 1998 Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.  
  20.          <6>     20/3/00    Quinn   Added MoreReplaceText and its support routines.  Added
  21.                                     MoreStrLen.  Tidied up a little.
  22.          <5>      1/3/00    Quinn   Minor Carbonation changes.
  23.          <4>     21/4/99    Quinn   Added ValidStringListHandle.
  24.          <3>     2/15/99    PCG     InlineGetHandleSize loses the Inline
  25.          <2>    11/11/98    PCG     fix header
  26.          <1>    11/10/98    PCG     first big re-org at behest of Quinn
  27.  
  28.     Old Change History (most recent first):
  29.  
  30.          <2>    10/23/98    PCG     add GetStringFromLongDouble
  31.          <1>     6/16/98    PCG     initial checkin
  32. */
  33.  
  34. /////////////////////////////////////////////////////////////////
  35.  
  36. // MoreIsBetter Setup
  37.  
  38. #include "MoreSetup.h"
  39.  
  40. // Our Prototypes
  41.  
  42. #include "MoreTextUtils.h"
  43.  
  44. // Mac OS Interfaces
  45.  
  46. #include <Resources.h>
  47. #include <PLStringFuncs.h>
  48. #include <Fonts.h>
  49.  
  50. // MIB Prototypes
  51.  
  52. #include "MoreMemory.h"
  53. #include "MoreQuickDraw.h"
  54.  
  55. /////////////////////////////////////////////////////////////////
  56.  
  57. pascal OSErr NewStringPtr (ConstStr255Param init, UInt8 maxSize, StringPtr *result)
  58. {
  59.     OSErr err = noErr;
  60.  
  61.     if (!MoreAssert (result && (!init || (*init <= maxSize))))
  62.         err = paramErr;
  63.     else
  64.     {
  65.         *result = StringPtr (NewPtr (1 + (maxSize ? maxSize : (init ? *init : 255))));
  66.  
  67.         if (!*result)
  68.             err = MemError ( );
  69.         else if (init && *init)
  70.             PLstrcpy (*result,init);
  71.         else
  72.             **result = 0;
  73.     }
  74.  
  75.     return err;
  76. }
  77.  
  78. pascal OSErr NewStringListHandle (Handle *h)
  79. {
  80.     DebugStr ("\pThis routine has never been traced.");
  81.  
  82.     if (!MoreAssert (h))
  83.         return nilHandleErr;
  84.     *h = NewHandleClear (sizeof (UInt16));
  85.     if (!*h)
  86.         return MemError ( );
  87.     return noErr;
  88. }
  89.  
  90. pascal OSErr AppendStringToListHandle (ConstStr255Param str, Handle h)
  91. {
  92.     DebugStr ("\pThis routine has never been traced.");
  93.  
  94.     OSErr err = noErr;
  95.  
  96.     if (!MoreAssert (h && *h))
  97.         err = nilHandleErr;
  98.     else
  99.     {
  100.         UInt8 dummyZero;
  101.  
  102.         if (!str)
  103.         {
  104.             dummyZero = 0;
  105.             str = &dummyZero;
  106.         }
  107.  
  108.         if (!(err = PtrAndHand (str, h, *str + 1)))
  109.             (** (UInt16 **) h) += 1;
  110.     }
  111.  
  112.     return err;
  113. }
  114.  
  115. pascal OSErr GetNewStringList (short resID, tStringListP *newStringList)
  116. {
  117.     OSErr err = noErr;
  118.  
  119.     Handle h = GetResource ('STR#',resID);
  120.  
  121.     if (!h)
  122.     {
  123.         err = ResError ( );
  124.         if (!err) err = resNotFound;
  125.     }
  126.     else
  127.     {
  128.         Size handleSize = GetHandleSize (h);
  129.         (void) MoreAssert (MemError ( ) == noErr);
  130.  
  131.         if (handleSize < 2)
  132.             err = paramErr;
  133.         else
  134.         {
  135.             UInt16    stringCount        = ** (UInt16 **) h;
  136.             Size    stringListSize    = sizeof (**newStringList) + (handleSize - 2) +
  137.                                         (stringCount * sizeof (StringPtr));
  138.  
  139.             *newStringList = (tStringListP) NewPtr (stringListSize);
  140.  
  141.             if (!*newStringList)
  142.                 err = MemError ( );
  143.             else
  144.             {
  145.                 (*newStringList)->count = stringCount;
  146.  
  147.                 if (stringCount)
  148.                 {
  149.                     UInt16 index = 0;
  150.  
  151.                     StringPtr stringScan = (StringPtr) ((*newStringList)->list + stringCount);
  152.  
  153.                     BlockMoveData (2 + *h, stringScan, handleSize - 2);
  154.  
  155.                     do
  156.                     {
  157.                         (*newStringList)->list [index] = stringScan;
  158.                         stringScan += *stringScan + 1;
  159.                     }
  160.                     while (++index < stringCount);
  161.                 }
  162.             }
  163.         }
  164.  
  165.         ReleaseResource (h);
  166.         (void) MoreAssert (ResError ( ) == noErr);
  167.     }
  168.  
  169.     return err;
  170. }
  171.  
  172. pascal Boolean ValidStringListHandle(Handle stringList)
  173.     // See comment in interface part.
  174. {
  175.     Boolean result;
  176.     UInt16 stringCount;
  177.     UInt16 stringIndex;
  178.     UInt8* cursor;
  179.     UInt8* bound;
  180.     ByteCount stringListLength;
  181.  
  182.     result = true;
  183.     if (stringList == NULL || *stringList == NULL || GetHandleSize(stringList) < sizeof(UInt16) ) {
  184.         result = false;
  185.     }
  186.     if (result) {
  187.         stringCount = *((UInt16 *) *stringList);
  188.         
  189.         stringListLength = GetHandleSize(stringList);
  190.         
  191.         // From here down we have to make sure we do nothing to move
  192.         // or purge until we're done with cursor and bound.
  193.         
  194.         cursor = ((UInt8 *)*stringList) + sizeof(UInt16);
  195.         bound  = ((UInt8 *)*stringList) + stringListLength;
  196.         for (stringIndex = 0; stringIndex < stringCount; stringIndex++) {
  197.             if ( cursor < bound ) {
  198.                 cursor += *cursor + 1;
  199.             } else {
  200.                 result = false;
  201.                 break;
  202.             }
  203.         }
  204.         
  205.         if (result) {
  206.             if ( cursor != bound ) {
  207.                 result = false;
  208.             }
  209.         }
  210.     }
  211.     
  212.     return result;
  213. }
  214.  
  215. pascal OSErr GetPascalStringFromLongDouble (long double d, SInt8 precision, StringPtr buf)
  216. {
  217.     OSErr err = noErr;
  218.  
  219.     *buf = 0;
  220.  
  221.     //    If client requests more precision than is available, bitch.
  222.  
  223.     if (!MoreAssert (precision < SIGDIGLEN))
  224.         err = paramErr;
  225.     else
  226.     {
  227.         //     If precision is less than 0, client is requesting
  228.         //    as much precision as is available.
  229.  
  230.         if (precision < 0)
  231.             precision = SIGDIGLEN;
  232.  
  233.         //    Try normal notation, and if that overflows,
  234.         //    fall back to scientific notation (bleah!).
  235.  
  236.         decimal dec;
  237.         decform df = { 1, 0, precision };
  238.  
  239.         num2dec (&df,d,&dec);
  240.  
  241.         if (dec.sig.text [0] == '?')
  242.         {
  243.             df.style    = 0;
  244.             df.digits    = SIGDIGLEN;
  245.  
  246.             num2dec (&df,d,&dec);
  247.         }
  248.  
  249.         if (*(dec.sig.text) == '0')
  250.             PLstrcpy (buf,"\p0");
  251.         else if (*(dec.sig.text) == 'I')
  252.             PLstrcpy (buf,"\p[INF]");
  253.         else if (*(dec.sig.text) == 'N')
  254.             PLstrcpy (buf,"\p[NaN]");
  255.         else
  256.         {
  257.             //    Finally, convert it to a pascal string...
  258.  
  259.             dec2str (&df,&dec,(Ptr)buf);
  260.             CopyCStringToPascal( (char *) buf, buf );
  261.  
  262.             //    ...and trim trailing zeroes.
  263.  
  264. //            if (df.style == 1 && dec.exp < 0)
  265. //                while (buf [*buf] == '0')
  266. //                    *buf -= 1;
  267.         }
  268.     }
  269.  
  270.     return err;
  271. }
  272.  
  273. // gDummyPort is a pointer to a dummy GrafPort whose font is always
  274. // the system font.  By setting thePort to this port, we can then safely
  275. // call Script Manager that get script information from the current port.
  276.  
  277. static GrafPtr gDummyPort;
  278.  
  279. extern pascal OSStatus InitMoreTextUtils(void)
  280.     // See comment in header.
  281. {
  282.     OSStatus err;
  283.     GrafPtr  oldPort;
  284.  
  285.     // Preserve the current port.
  286.         
  287.     GetPort(&oldPort);
  288.     
  289.     // Create gDummyPort.
  290.     
  291.     gDummyPort = (GrafPtr) CreateNewPort();
  292.     err = MoreMemError(gDummyPort);
  293.     if (err == noErr) {
  294.     
  295.         // CreateNewPort, if it follows the semantics of the old
  296.         // OpenPort routine, should set thePort to the new port.
  297.         // This assert ensures that behaviour, because the following
  298.         // call to TextFont relies on it.
  299.         
  300.         #if MORE_DEBUG
  301.             {
  302.                 GrafPtr junkPort;
  303.                 
  304.                 GetPort(&junkPort);
  305.                 MoreAssertQ(junkPort == gDummyPort);
  306.             }
  307.         #endif
  308.  
  309.         // Set the dummy port’s font to the system font.
  310.                 
  311.         TextFont(systemFont);
  312.     }
  313.     
  314.     SetPort(oldPort);
  315.     
  316.     return err;
  317. }
  318.  
  319. extern pascal void TermMoreTextUtils(void)
  320.     // See comment in header.
  321. {
  322.     if (gDummyPort != nil) {
  323.         DisposePort( (CGrafPtr) gDummyPort);
  324.         gDummyPort = nil;
  325.     }
  326. }
  327.  
  328. extern pascal void MoreReplaceText(Str255 baseText, ConstStr255Param substitutionText, ConstStr15Param key)
  329.     // See comment in header.
  330. {
  331.     OSStatus err;
  332.     GrafPtr  oldPort;
  333.     Handle   baseTextH;
  334.     Handle   substitutionTextH;
  335.     Size     newLength;
  336.     UInt8      *tmpKey;
  337.  
  338.     MoreAssertQ(baseText != nil);
  339.     MoreAssertQ(substitutionText != nil);
  340.     MoreAssertQ(key != nil);
  341.     MoreAssertQ(key[0] <= 15);
  342.     
  343.     GetPort(&oldPort);
  344.     
  345.     baseTextH = nil;
  346.     substitutionTextH = nil;
  347.  
  348.     // Copy the strings into handles, call ReplaceText, then
  349.     // copy the result back into baseText (making sure that
  350.     // there is at most 255 bytes in the resulting string).
  351.         
  352.     err = noErr;
  353.     if (gDummyPort == nil) {
  354.         err = InitMoreTextUtils();
  355.     }
  356.     if (err == noErr) {
  357.         SetPort(gDummyPort);
  358.  
  359.         err = PtrToHand(&baseText[1], &baseTextH, baseText[0]);
  360.     }
  361.     if (err == noErr) {
  362.         err = PtrToHand(&substitutionText[1], &substitutionTextH, substitutionText[0]);
  363.     }
  364.     if (err == noErr) {
  365.         tmpKey = (UInt8 *) key;
  366.         err = ReplaceText(baseTextH, substitutionTextH, tmpKey);
  367.         if (err >= 0) {
  368.             newLength = GetHandleSize(baseTextH);
  369.             if (newLength > 255) {
  370.                 newLength = 255;
  371.             }
  372.             baseText[0] = newLength;
  373.             BlockMoveData(*baseTextH, &baseText[1], newLength);
  374.             err = noErr;
  375.         }
  376.     }
  377.     
  378.     // Clean up.
  379.  
  380.     if (baseTextH != nil) {
  381.         DisposeHandle(baseTextH);
  382.         MoreAssertQ(MemError() == noErr);
  383.     }    
  384.     if (substitutionTextH != nil) {
  385.         DisposeHandle(substitutionTextH);
  386.         MoreAssertQ(MemError() == noErr);
  387.     }    
  388.     SetPort(oldPort);
  389.     
  390.     MoreAssert(err == noErr);
  391. }
  392.  
  393. extern pascal ByteCount MoreStrLen(const char *str)
  394.     // See comment in header.
  395. {
  396.     ByteCount result;
  397.     
  398.     result = 0;
  399.     while ( *str != 0 ) {
  400.         result += 1;
  401.         str += 1;
  402.     }
  403.     return result;
  404. }
  405.